/***********************************************************************************************//**
 * \file   main.c
 * \brief  Silicon Labs Empty Example Project
 *
 * This example demonstrates the bare minimum needed for a Blue Gecko C application
 * that allows Over-the-Air Device Firmware Upgrading (OTA DFU). The application
 * starts advertising after boot and restarts advertising after a connection is closed.
 ***************************************************************************************************
 * <b> (C) Copyright 2016 Silicon Labs, http://www.silabs.com</b>
 ***************************************************************************************************
 * This file is licensed under the Silabs License Agreement. See the file
 * "Silabs_License_Agreement.txt" for details. Before using this software for
 * any purpose, you must agree to the terms of that agreement.
 **************************************************************************************************/

#ifndef GENERATION_DONE
#error You must run generate first!
#endif

#include "stdio.h"
/* Board headers */
#include "boards.h"
#include "ble-configuration.h"
#include "board_features.h"

/* Bluetooth stack headers */
#include "bg_types.h"
#include "native_gecko.h"
#include "bg_dfu.h"
#include "gatt_db.h"
#include "aat.h"

/* Libraries containing default Gecko configuration values */
#include "em_emu.h"
#include "em_cmu.h"
#include "em_cryotimer.h"
#include "em_gpio.h"
#include "em_usart.h"
#ifdef FEATURE_BOARD_DETECTED
#include "bspconfig.h"
#include "pti.h"
#endif /* FEATURE_BOARD_DETECTED */

#ifdef FEATURE_IOEXPANDER
#include "ioexp.h"
#endif /* FEATURE_IOEXPANDER */

/* Device initialization header */
#include "InitDevice.h"

#ifdef FEATURE_SPI_FLASH
#include "flashpwr.h"
#endif /* FEATURE_SPI_FLASH */

#include "dtm.h"


/***********************************************************************************************//**
 * @addtogroup Application
 * @{
 **************************************************************************************************/

/***********************************************************************************************//**
 * @addtogroup app
 * @{
 **************************************************************************************************/

#ifndef MAX_CONNECTIONS
#define MAX_CONNECTIONS 4
#endif
uint8_t bluetooth_stack_heap[DEFAULT_BLUETOOTH_HEAP(MAX_CONNECTIONS)];

#ifdef FEATURE_PTI_SUPPORT
static const RADIO_PTIInit_t ptiInit = RADIO_PTI_INIT;
#endif

/* Gecko configuration parameters (see gecko_configuration.h) */
static const gecko_configuration_t config = {
  .config_flags=0,
  .bluetooth.max_connections=MAX_CONNECTIONS,
  .bluetooth.heap=bluetooth_stack_heap,
  .bluetooth.heap_size=sizeof(bluetooth_stack_heap),
  .gattdb=&bg_gattdb_data,
  .ota.flags=0,
  .ota.device_name_len=3,
  .ota.device_name_ptr="OTA",
  #ifdef FEATURE_PTI_SUPPORT
  .pti = &ptiInit,
  #endif
};

enum signal
{
  signal_testmode_command_ready = 1,
};

void USART0_RX_IRQHandler(void)
{
  testmode_process_command_byte(USART_Rx(USART0));
}

void USART0_Tx(uint8_t data)
{
  USART_Tx(USART0, data);
}

static const struct testmode_config testmode_config = {
  .write_response_byte = USART0_Tx,
  .get_ticks = CRYOTIMER_CounterGet,
  .ticks_per_second = 32768,
  .command_ready_signal = signal_testmode_command_ready,
};

void bleUSARTInit(uint32_t baud);

/**
 * @brief  Main function
 */
void main(void)
{

#ifdef FEATURE_SPI_FLASH
  /* Put the SPI flash into Deep Power Down mode for those radio boards where it is available */
  flashpwrInit();
  flashpwrDeepPowerDown();
#endif

  /* Initialize peripherals */
  enter_DefaultMode_from_RESET();

  /* Initialize stack */
  gecko_init(&config);

#ifdef FEATURE_IOEXPANDER
  if (IOEXP_STATUS_OK == IOEXP_Init())
  {
    IOEXP_VCOMEnable(false);
  }
#endif /* FEATURE_IOEXPANDER */

  GPIO_PinModeSet(keyport, keypin, gpioModeInputPull, 1);//F2
  //GPIO_IntConfig(gpioPortF, 2, false, true, true);
  //NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
  //NVIC_EnableIRQ(GPIO_EVEN_IRQn);

  bleUSARTInit(115200);
  //USART_IntEnable(USART0, USART_IF_RXDATAV);
  //NVIC_EnableIRQ(USART0_RX_IRQn);

  testmode_init(&testmode_config);

  printf("Enter DTM model\r\n");

  uint16_t i = 0;

  while (1)
  {
    /* Event pointer for handling events */
    struct gecko_cmd_packet* evt;

    /* Check for stack event. */
    evt = gecko_wait_event();

    testmode_handle_gecko_event(evt);

    //printf("Runing...%d\r\n",i ++);
  }
}

void GPIO_EVEN_IRQHandler(void)
{
	uint32_t iflags;
	/* Get all ODD interrupts. */
	iflags = GPIO_IntGetEnabled() & 0x00005555;
	/* Clean only ODD interrupts. */
	GPIO_IntClear(iflags);

	if (iflags & (0x00000001 << 2))
	{
		//printf("key press\r\n");
	}

}


void bleUSARTInit(uint32_t baud)
{
	// $[USART_InitAsync]
	USART_InitAsync_TypeDef initasync = USART_INITASYNC_DEFAULT;

	initasync.enable = usartDisable;
	initasync.baudrate = baud;
	initasync.databits = usartDatabits8;
	initasync.parity = usartNoParity;
	initasync.stopbits = usartStopbits1;
	initasync.oversampling = usartOVS8;
#if defined( USART_INPUT_RXPRS ) && defined( USART_CTRL_MVDIS )
	initasync.mvdis = 0;
	initasync.prsRxEnable = 0;
	initasync.prsRxCh = (USART_PrsRxCh_TypeDef)0;
#endif

	CMU_ClockEnable(cmuClock_USART0, true);
	CMU_ClockEnable(cmuClock_GPIO, true);

	USART_InitAsync(USART0, &initasync);
	USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;

	initprs.rxTriggerEnable = 0;
	initprs.txTriggerEnable = 0;
	initprs.prsTriggerChannel = usartPrsTriggerCh0;

	USART_InitPrsTrigger(USART0, &initprs);
	USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
			| USART_ROUTELOC0_CLKLOC_LOC4;
	USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CLKPEN);
	/* Disable CS pin */
	USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
			| USART_ROUTELOC0_CSLOC_LOC3;
	USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
	/* Disable CTS pin */
	USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
			| USART_ROUTELOC1_CTSLOC_LOC2;
	USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
	/* Disable RTS pin */
	USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
			| USART_ROUTELOC1_RTSLOC_LOC1;
	USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);

	/* Set up RX pin */
	USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
			| USART_ROUTELOC0_RXLOC_LOC15;
	USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_RXPEN;
	/* Set up TX pin */
	USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
			| USART_ROUTELOC0_TXLOC_LOC15;
	USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_TXPEN;

	USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSEN);
	/* Set CTS active low */
	USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSINV);
	/* Set RTS active low */
	USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_RTSINV);
	/* Set CS active low */
	USART0->CTRL = USART0->CTRL & (~USART_CTRL_CSINV);
	/* Set TX active high */
	USART0->CTRL = USART0->CTRL & (~USART_CTRL_TXINV);
	/* Set RX active high */
	USART0->CTRL = USART0->CTRL & (~USART_CTRL_RXINV);

	/* Enable USART if opted by user */
	USART_Enable(USART0, usartEnable);
	// [USART_Enable]$

	/* Pin PC10 is configured to Push-pull */
	GPIO_PinModeSet(gpioPortC, 10, gpioModePushPull, 1);
	/* Pin PC11 is configured to Input enabled */
	GPIO_PinModeSet(gpioPortC, 11, gpioModeInput, 1);


	/* Clear previous RX interrupts */
	USART_IntClear(USART0, USART_IEN_RXDATAV);
	NVIC_ClearPendingIRQ(USART0_RX_IRQn);
	/* Enable RX interrupts */
	USART_IntEnable(USART0,USART_IEN_RXDATAV);
	NVIC_EnableIRQ(USART0_RX_IRQn);
	// [USART_InitPrsTrigger]$
}

size_t __write(int handle, const unsigned char * buffer, unsigned char size)
{
	/* Remove the #if #endif pair to enable the implementation */
	unsigned char nChars = 0;
	if (buffer == 0)
	{
		return 0;
	}
	for (/* Empty */; size != 0; --size)
	{
		USART_Tx(USART0,(char)buffer[nChars]);
		++ nChars;
	}
	return nChars;
}
/** @} (end addtogroup app) */
/** @} (end addtogroup Application) */
